const core = require("@babel/core");
let types = require("babel-types");//创建节点工厂函数
//let babelPluginTransformEs2015ArrowFunctions = require("babel-plugin-transform-es2015-arrow-functions");
//访问者模式 访问器模式 迭代器 for(let key in obj){} 怎么遍历不管取出
//访问者 用户固定
let babelPluginTransformEs2015ArrowFunctions = {
  visitor: {
    //访问者 内部怎么实现不关心
    ArrowFunctionExpression(nodePath) {
      let node = nodePath.node; //节点
      hoistFunctionEnvironment(nodePath); //环境提升
      node.type = "FunctionExpression";
    },
  },
};

function hoistFunctionEnvironment(fnPath) {
  // fnPath.findParent=(judge)=>{
  //   let parentPath = this.parentPath;
  //   while (parentPath) {
  //     if (judge(parentPath)) {
  //       return parentPath
  //     }else{
  //       parentPath = parentPath.parentPath;
  //     }
  //   }
  // }
  const thisEnvFn = fnPath.findParent((p) => {
    //以下两种写法等价 内置方法
    //return (types.isFunction(p.node)&&types.isArrowFunctionExpression(p.node)||types.isProgram(p.node))
    //普通函数或者根节点isProgram
    return (p.isFunction() && !p.isArrowFunctionExpression()) || p.isProgram();
  });
  let thisPaths = getScopeInformation(fnPath); //[]
  if (thisPaths.length > 0) {
    let thisBinding = "_this";
    //types 1.用来判断某个节点是不是某个类型 2.用来创建一个新的节点
    let _thisIdentifier = types.identifier(thisBinding);
    thisEnvFn.scope.push({
      //var _this = this;
      type: "VariableDeclarator",
      id: _thisIdentifier,
      init: types.thisExpression(),
    });
    thisPaths.forEach((thisPath) => {
      thisPath.replaceWith(_thisIdentifier);
    });
  }
}

function getScopeInformation(fnPath) {
  let thisPaths = [];
  fnPath.traverse({
    ThisExpression(thisPath) {
      thisPaths.push(thisPath);
    },
  });
  return thisPaths;
}

let sourceCode = `
//全局
const sum = (a,b)=>{
    console.log(this);
    console.log(this);
    return a+b
}
`;
let { code } = core.transform(sourceCode, {
  plugins: [babelPluginTransformEs2015ArrowFunctions],
});
console.log(code);

//节点是一个属性

//JS转换的原理是转换AST语法树
